package com.frinder.base.akka;

import akka.actor.ActorRef;
import akka.actor.ActorSelection;
import akka.actor.ActorSystem;
import akka.actor.PoisonPill;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @author frinder
 * @date 2018/6/5
 * @className Actors
 * @package com.kiktech.base.akka
 * @Description: Actor 路径定义
 */
@Component
public class Actors {

    /**
     * 路径前缀
     */
    public static final String ACTOR_PREFIX = "akka://ActorSystem/user/";

    @Autowired
    private ActorSystem actorSystem;

    @Autowired
    private SpringExtension springExtension;


    /**
     * 获取 actor 全路径
     *
     * @param suffix
     * @return
     */
    public String getPath(String suffix) {
        return ACTOR_PREFIX + "/" + suffix;
    }


    /**
     * 根据 path 获取 ActorSelection
     *
     * @param suffix 路径名称，即 getActorRef 中的 actorName
     * @return
     */
    public ActorSelection getActorSelection(String suffix) {
        return actorSystem.actorSelection(getPath(suffix));
    }


    /**
     * 根据 bean 获取 ActorRef（带构造方法参数）
     *
     * @param actorBeanName spring容器中bean名称，默认为类名（首字母小定）
     * @param actorName     actor容器中actor名称
     * @param args          bean构造方法参数列表
     * @return
     */
    public ActorRef getActorRef(String actorBeanName, String actorName, Object... args) {
        return actorSystem.actorOf(springExtension.props(actorBeanName, args).withMailbox("akka.priority-mailbox"), actorName);
    }

    /**
     * 根据 bean 获取 ActorRef（不带构造方法参数）
     *
     * @param actorBeanName spring容器中bean名称，默认为类名（首字母小定）
     * @param args          bean构造方法参数列表
     * @return
     */
    public ActorRef getActorRef(String actorBeanName, Object... args) {
        return actorSystem.actorOf(springExtension.props(actorBeanName, args).withMailbox("akka.priority-mailbox"));
    }

    /**
     * 杀死 actor
     *
     * @param suffix
     */
    public void destroyActor(String suffix) {
        getActorSelection(suffix).tell(PoisonPill.getInstance(), ActorRef.noSender());
    }

}
